package com.kfyang.manualgear.generator.impl.jdbc.orm;

import static com.kfyang.manualgear.generator.impl.jdbc.constant.StatementConstants.*;
import static com.kfyang.manualgear.generator.impl.jdbc.constant.SqlConstants.*;

import com.kfyang.manualgear.struct.EntityInfo;
import com.kfyang.manualgear.util.GlobalConfigUtils;
import com.kfyang.manualgear.struct.FieldInfo;
import com.kfyang.manualgear.util.StringUtils;
import com.squareup.javapoet.MethodSpec;

import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;

import static com.kfyang.manualgear.constant.Constants.*;

public class SelectMethod extends AbstractMethod {


    protected SelectMethod(MethodSpec.Builder methodBuilder, EntityInfo entityInfo, boolean forOne) {
        super(methodBuilder, entityInfo, forOne);
    }

    @Override
    protected void prepareSql() {
        StringBuilder sqlBuilder = new StringBuilder(SQL_DEFINE + SELECT_SQL);
        List<Object> parameters = new ArrayList<>();

        parameters.add(generateSelectList());
        parameters.add(entityInfo.tableName);

        if (forOne) {
            parameters.add(entityInfo.idInfo.col);
            sqlBuilder.append(" where $L = ?");
        }
        if (entityInfo.deleteInfo != null) {
            parameters.add(entityInfo.deleteInfo.col);
            sqlBuilder.append(forOne ? AND : WHERE).append("$L = " + NOT_DELETED);
        }
        sqlBuilder.append(QUOTA);

        methodBuilder.addStatement(sqlBuilder.toString(), parameters.toArray());
    }

    @Override
    public void addReturn() {
        if (forOne) {
            methodBuilder.beginControlFlow(QUERY_BEGIN_ONE);
        } else {
            methodBuilder.beginControlFlow(QUERY_BEGIN_MANY);
        }

        methodBuilder.addStatement(NEW_ENTITY_STATEMENT, entityInfo.entityTypeName, entityInfo.entityTypeName);

        entitySetAttributes();

        methodBuilder.addStatement(RETURN_ENTITY);
        methodBuilder.endControlFlow((forOne ? ", id)" : RIGHT_ROUND_BRACKET));
    }

    /**
     * 生成 select 语句的结果列表
     * @return 结果列表
     */
    private String generateSelectList() {
        int colPos = 0;
        StringJoiner selectList = new StringJoiner(COMMA);
        selectList.add(entityInfo.idInfo.col + BLANK + GlobalConfigUtils.alias[colPos++]);
        for (FieldInfo fieldInfo : entityInfo.fieldInfos) {
            selectList.add(fieldInfo.col + BLANK + GlobalConfigUtils.alias[colPos++]);
        }
        if (entityInfo.createTimeInfo != null) {
            selectList.add(entityInfo.createTimeInfo.col + BLANK + GlobalConfigUtils.alias[colPos++]);
        }
        if (entityInfo.updateTimeInfo != null) {
            selectList.add(entityInfo.updateTimeInfo.col + BLANK + GlobalConfigUtils.alias[colPos++]);
        }
        if (entityInfo.deleteInfo != null) {
            selectList.add(entityInfo.deleteInfo.col + BLANK + GlobalConfigUtils.alias[colPos]);
        }
        return selectList.toString();
    }

    /**
     * 设置实体类的属性
     */
    private void entitySetAttributes() {
        int colPos = 0;
        entitySetStatement(entityInfo.idInfo, colPos++);
        for (FieldInfo fieldInfo : entityInfo.fieldInfos) {
            entitySetStatement(fieldInfo, colPos++);
        }
        if (entityInfo.createTimeInfo != null) {
            entitySetStatement(entityInfo.createTimeInfo, colPos++);
        }
        if (entityInfo.updateTimeInfo != null) {
            entitySetStatement(entityInfo.updateTimeInfo, colPos++);
        }
        if (entityInfo.deleteInfo != null) {
            entitySetStatement(entityInfo.deleteInfo, colPos);
        }
    }

    /**
     * 设置实体类的属性的工具方法
     * @param fieldInfo 字段信息
     * @param colPos 列索引
     */
    private void entitySetStatement(FieldInfo fieldInfo, int colPos) {
        methodBuilder.addStatement(ENTITY_SET_STATEMENT,
            StringUtils.toSetMethod(fieldInfo.field), fieldInfo.handler.className, fieldInfo.handler.methodName, GlobalConfigUtils.alias[colPos]);
    }
}
